added SSCLI 1.0
[windows-sources.git] / sdk / samples / all in on code / Visual Studio 2010 / CSFTPDownload / FTPDownloadClient.cs
blobc52558b0fb09edc10a83c4046a1a8a5961126d5b
1 /****************************** Module Header ******************************\
2 * Module Name: FTPDownloadClient.cs
3 * Project: CSFTPDownload
4 * Copyright (c) Microsoft Corporation.
5 *
6 * This class is used to download files from a FTP server. When the download
7 * starts, it will download the file in a background thread. The downloaded
8 * data is stored in a MemoryStream first, and then written to local file.
9 *
11 * This source is subject to the Microsoft Public License.
12 * See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
13 * All other rights reserved.
15 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
16 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
18 \***************************************************************************/
20 using System;
21 using System.Collections.Generic;
22 using System.IO;
23 using System.Net;
24 using System.Threading;
26 namespace CSFTPDownload
28 public partial class FTPClientManager
31 public class FTPDownloadClient
33 // 2M bytes.
34 public const int MaxCacheSize = 2097152;
36 // 2K bytes.
37 public const int BufferSize = 2048;
39 FTPClientManager manager;
41 public event EventHandler<FileDownloadCompletedEventArgs>
42 FileDownloadCompleted;
44 public event EventHandler AllFilesDownloadCompleted;
46 public FTPDownloadClient(FTPClientManager manager)
48 if (manager == null)
50 throw new ArgumentNullException("FTPClientManager cannot be null.");
53 this.manager = manager;
56 /// <summary>
57 /// Download files, directories and their subdirectories.
58 /// </summary>
59 public void DownloadDirectoriesAndFiles(IEnumerable<FTPFileSystem> files,
60 string localPath)
62 if (files == null)
64 throw new ArgumentNullException(
65 "The files to download cannot be null.");
68 // Create a thread to download data.
69 ParameterizedThreadStart threadStart =
70 new ParameterizedThreadStart(StartDownloadDirectoriesAndFiles);
71 Thread downloadThread = new Thread(threadStart);
72 downloadThread.IsBackground = true;
73 downloadThread.Start(new object[] { files, localPath });
76 /// <summary>
77 /// Download files, directories and their subdirectories.
78 /// </summary>
79 void StartDownloadDirectoriesAndFiles(object state)
81 var paras = state as object[];
83 IEnumerable<FTPFileSystem> files = paras[0] as IEnumerable<FTPFileSystem>;
84 string localPath = paras[1] as string;
86 foreach (var file in files)
88 DownloadDirectoryOrFile(file, localPath);
91 this.OnAllFilesDownloadCompleted(EventArgs.Empty);
94 /// <summary>
95 /// Download a single file or directory.
96 /// </summary>
97 void DownloadDirectoryOrFile(FTPFileSystem fileSystem, string localPath)
100 // Download the file directly.
101 if (!fileSystem.IsDirectory)
103 DownloadFile(fileSystem, localPath);
106 // Download a directory.
107 else
110 // Construct the directory Path.
111 string directoryPath = localPath + "\\" + fileSystem.Name;
113 if (!Directory.Exists(directoryPath))
115 Directory.CreateDirectory(directoryPath);
118 // Get the sub directories and files.
119 var subDirectoriesAndFiles =
120 this.manager.GetSubDirectoriesAndFiles(fileSystem.Url);
122 // Download the files in the folder and sub directories.
123 foreach (var subFile in subDirectoriesAndFiles)
125 DownloadDirectoryOrFile(subFile, directoryPath);
130 /// <summary>
131 /// Download a single file directly.
132 /// </summary>
133 void DownloadFile(FTPFileSystem file, string localPath)
135 if (file.IsDirectory)
137 throw new ArgumentException(
138 "The FTPFileSystem to download is a directory in fact");
141 string destPath = localPath + "\\" + file.Name;
143 // Create a request to the file to be downloaded.
144 FtpWebRequest request = WebRequest.Create(file.Url) as FtpWebRequest;
146 request.Credentials = this.manager.Credentials;
148 // Download file.
149 request.Method = WebRequestMethods.Ftp.DownloadFile;
151 FtpWebResponse response = null;
152 Stream responseStream = null;
153 MemoryStream downloadCache = null;
159 // Retrieve the response from the server and get the response stream.
160 response = request.GetResponse() as FtpWebResponse;
162 this.manager.OnNewMessageArrived(new NewMessageEventArg
164 NewMessage = response.StatusDescription
167 responseStream = response.GetResponseStream();
169 // Cache data in memory.
170 downloadCache = new MemoryStream(FTPDownloadClient.MaxCacheSize);
171 byte[] downloadBuffer = new byte[FTPDownloadClient.BufferSize];
173 int bytesSize = 0;
174 int cachedSize = 0;
176 // Download the file until the download is completed.
177 while (true)
180 // Read a buffer of data from the stream.
181 bytesSize = responseStream.Read(downloadBuffer, 0,
182 downloadBuffer.Length);
184 // If the cache is full, or the download is completed, write
185 // the data in cache to local file.
186 if (bytesSize == 0
187 || MaxCacheSize < cachedSize + bytesSize)
191 // Write the data in cache to local file.
192 WriteCacheToFile(downloadCache, destPath, cachedSize);
194 // Stop downloading the file if the download is paused,
195 // canceled or completed.
196 if (bytesSize == 0)
198 break;
201 // Reset cache.
202 downloadCache.Seek(0, SeekOrigin.Begin);
203 cachedSize = 0;
205 catch (Exception ex)
207 string msg = string.Format(
208 "There is an error while downloading {0}. "
209 + " See InnerException for detailed error. ",
210 file.Url);
211 ApplicationException errorException
212 = new ApplicationException(msg, ex);
214 // Fire the DownloadCompleted event with the error.
215 ErrorEventArgs e = new ErrorEventArgs
217 ErrorException = errorException
220 this.manager.OnErrorOccurred(e);
222 return;
227 // Write the data from the buffer to the cache in memory.
228 downloadCache.Write(downloadBuffer, 0, bytesSize);
229 cachedSize += bytesSize;
232 var fileDownloadCompletedEventArgs = new FileDownloadCompletedEventArgs
235 LocalFile = new FileInfo(destPath),
236 ServerPath = file.Url
239 this.OnFileDownloadCompleted(fileDownloadCompletedEventArgs);
241 finally
243 if (response != null)
245 response.Close();
248 if (responseStream != null)
250 responseStream.Close();
253 if (downloadCache != null)
255 downloadCache.Close();
260 /// <summary>
261 /// Write the data in cache to local file.
262 /// </summary>
263 void WriteCacheToFile(MemoryStream downloadCache, string downloadPath,
264 int cachedSize)
266 using (FileStream fileStream = new FileStream(downloadPath,
267 FileMode.Append))
269 byte[] cacheContent = new byte[cachedSize];
270 downloadCache.Seek(0, SeekOrigin.Begin);
271 downloadCache.Read(cacheContent, 0, cachedSize);
272 fileStream.Write(cacheContent, 0, cachedSize);
276 protected virtual void OnFileDownloadCompleted(FileDownloadCompletedEventArgs e)
279 if (FileDownloadCompleted != null)
281 FileDownloadCompleted(this, e);
285 protected virtual void OnAllFilesDownloadCompleted(EventArgs e)
287 if (AllFilesDownloadCompleted != null)
289 AllFilesDownloadCompleted(this, e);